Hệ thống quản lý phòng khám trực tuyến bằng PHP

1 <?php
2
3     #########################################################
4     
/*
5     ~~~~~~ LIST OF FUNCTIONS ~~~~~~
6         getTableList() -- returns an associative array (tableName => tableData, tableData
is array(tableCaption, tableDescription, tableIcon)) of tables accessible by current user
7         get_table_groups() -- returns an associative array (table_group => tables_array)
8         getLoggedMemberID() -- returns memberID of logged member. If no login, returns anonymous memberID
9         getLoggedGroupID() -- returns groupID of logged member, or anonymous groupID
10         logOutMember() -- destroys session and logs member
out.
11         logInMember() -- checks POST login. If not valid, redirects to index.php,
else returns TRUE
12         getTablePermissions($tn) -- returns an array of permissions allowed
for logged member to given table (allowAccess, allowInsert, allowView, allowEdit, allowDelete) -- allowAccess is set to true if any access level is allowed
13         get_sql_fields($tn) -- returns the SELECT part of the table view query
14         get_sql_from($tn[,
true]) -- returns the FROM part of the table view query, with full joins, optionally skipping permissions if true passed as 2nd param.
15         get_joined_record($table, $id[,
true]) -- returns assoc array of record values for given PK value of given table, with full joins, optionally skipping permissions if true passed as 3rd param.
16         get_defaults($table) -- returns assoc array of table fields
as array keys and default values (or empty), excluding automatic values as array values
17         htmlUserBar() -- returns html code
for displaying user login status to be used on top of pages.
18         showNotifications($msg, $
class) -- returns html code for displaying a notification. If no parameters provided, processes the GET request for possible notifications.
19         parseMySQLDate(a, b) -- returns a
if valid mysql date, or b if valid mysql date, or today if b is true, or empty if b is false.
20         parseCode(code) -- calculates and returns special values to be inserted
in automatic fields.
21         addFilter(i, filterAnd, filterField, filterOperator, filterValue) -- enforce a filter over data
22         clearFilters() -- clear all filters
23         getMemberInfo() -- returns an array containing the currently signed-
in member's info
24         loadView($view, $data) -- passes $data to templates/{$view}.php and returns the output
25         loadTable($table, $data) -- loads table template, passing $data to it
26         filterDropdownBy($filterable, $filterers, $parentFilterers, $parentPKField, $parentCaption, $parentTable, &$filterableCombo) -- applies cascading drop-downs
for a lookup field, returns js code to be inserted into the page
27         br2nl($text) -- replaces all variations of HTML <br> tags with a
new line character
28         htmlspecialchars_decode($text) -- inverse of htmlspecialchars()
29         entitiesToUTF8($text) -- convert unicode entities (e.g. &#
1234;) to actual UTF8 characters, requires multibyte string PHP extension
30         func_get_args_byref() -- returns an array of arguments passed to a function,
by reference
31         permissions_sql($table, $level) -- returns an array containing the FROM and WHERE additions
for applying permissions to an SQL query
32         error_message($msg[, $back_url]) -- returns html code
for a styled error message .. pass explicit false in second param to suppress back button
33         toMySQLDate($formattedDate, $sep = datalist_date_separator, $ord = datalist_date_format)
34         reIndex(&$arr) -- returns a copy of the given array, with keys replaced
by 1-based numeric indices, and values replaced by original keys
35         get_embed($provider, $url[, $width, $height, $retrieve]) -- returns embed code
for a given url (supported providers: youtube, googlemap)
36         check_record_permission($table, $id, $perm =
'view') -- returns true if current user has the specified permission $perm ('view', 'edit' or 'delete') for the given recors, false otherwise
37         NavMenus($options) -- returns the HTML code
for the top navigation menus. $options is not implemented currently.
38         StyleSheet() -- returns the HTML code
for included style sheet files to be placed in the <head> section.
39         getUploadDir($dir) --
if dir is empty, returns upload dir configured in defaultLang.php, else returns $dir.
40         PrepareUploadedFile($FieldName, $MaxSize, $FileTypes=
'jpg|jpeg|gif|png', $NoRename=false, $dir="") -- validates and moves uploaded file for given $FieldName into the given $dir (or the default one if empty)
41         get_home_links($homeLinks, $default_classes, $tgroup) -- process $homeLinks array and
return custom links for homepage. Applies $default_classes to links if links have classes defined, and filters links by $tgroup (using '*' matches all table_group values)
42     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43     */

44
45     #########################################################
46
47     function getTableList($skip_authentication =
false){
48         $arrAccessTables = array();
49         $arrTables = array(
50             
'patients' => array('Patients', '', 'resources/table_icons/administrator.png', 'None'),
51             
'disease_symptoms' => array('Disease symptoms', '', 'resources/table_icons/health.png', 'None'),
52             
'medical_records' => array('Medical Records', '', 'resources/table_icons/cash_terminal.png', 'None'),
53             
'events' => array('Appointments', '', 'table.gif', 'None')
54         );
55         
if($skip_authentication || getLoggedAdmin()) return $arrTables;
56
57         
if(is_array($arrTables)){
58             
foreach($arrTables as $tn => $tc){
59                 $arrPerm = getTablePermissions($tn);
60                 
if($arrPerm[0]){
61                     $arrAccessTables[$tn] = $tc;
62                 }
63             }
64         }
65
66         
return $arrAccessTables;
67     }
68
69     #########################################################
70
71     function get_table_groups($skip_authentication =
false){
72         $tables = getTableList($skip_authentication);
73         $all_groups = array(
'None');
74
75         $groups = array();
76         
foreach($all_groups as $grp){
77             
foreach($tables as $tn => $td){
78                 
if($td[3] && $td[3] == $grp) $groups[$grp][] = $tn;
79                 
if(!$td[3]) $groups[0][] = $tn;
80             }
81         }
82
83         
return $groups;
84     }
85
86     #########################################################
87
88     function getTablePermissions($tn){
89         
static $table_permissions = array();
90         
if(isset($table_permissions[$tn])) return $table_permissions[$tn];
91
92         $groupID = getLoggedGroupID();
93         $memberID = makeSafe(getLoggedMemberID());
94         $res_group = sql(
"select tableName, allowInsert, allowView, allowEdit, allowDelete from membership_grouppermissions where groupID='{$groupID}'", $eo);
95         $res_user = sql(
"select tableName, allowInsert, allowView, allowEdit, allowDelete from membership_userpermissions where lcase(memberID)='{$memberID}'", $eo);
96
97         
while($row = db_fetch_assoc($res_group)){
98             $table_permissions[$row[
'tableName']] = array(
99                 
1 => intval($row['allowInsert']),
100                 
2 => intval($row['allowView']),
101                 
3 => intval($row['allowEdit']),
102                 
4 => intval($row['allowDelete']),
103                 
'insert' => intval($row['allowInsert']),
104                 
'view' => intval($row['allowView']),
105                 
'edit' => intval($row['allowEdit']),
106                 
'delete' => intval($row['allowDelete'])
107             );
108         }
109
110         
// user-specific permissions, if specified, overwrite his group permissions
111         
while($row = db_fetch_assoc($res_user)){
112             $table_permissions[$row[
'tableName']] = array(
113                 
1 => intval($row['allowInsert']),
114                 
2 => intval($row['allowView']),
115                 
3 => intval($row['allowEdit']),
116                 
4 => intval($row['allowDelete']),
117                 
'insert' => intval($row['allowInsert']),
118                 
'view' => intval($row['allowView']),
119                 
'edit' => intval($row['allowEdit']),
120                 
'delete' => intval($row['allowDelete'])
121             );
122         }
123
124         
// if user has any type of access, set 'access' flag
125         
foreach($table_permissions as $t => $p){
126             $table_permissions[$t][
'access'] = $table_permissions[$t][0] = false;
127
128             
if($p['insert'] || $p['view'] || $p['edit'] || $p['delete']){
129                 $table_permissions[$t][
'access'] = $table_permissions[$t][0] = true;
130             }
131         }
132
133         
return $table_permissions[$tn];
134     }
135
136     #########################################################
137
138     function get_sql_fields($table_name){
139         $sql_fields = array(
140             
'patients' => "`patients`.`id` as 'id', `patients`.`last_name` as 'last_name', `patients`.`first_name` as 'first_name', `patients`.`gender` as 'gender', `patients`.`sexual_orientation` as 'sexual_orientation', if(`patients`.`birth_date`,date_format(`patients`.`birth_date`,'%m/%d/%Y'),'') as 'birth_date', `patients`.`age` as 'age', `patients`.`image` as 'image', `patients`.`address` as 'address', `patients`.`city` as 'city', `patients`.`state` as 'state', `patients`.`zip` as 'zip', CONCAT_WS('-', LEFT(`patients`.`home_phone`,3), MID(`patients`.`home_phone`,4,3), RIGHT(`patients`.`home_phone`,4)) as 'home_phone', CONCAT_WS('-', LEFT(`patients`.`work_phone`,3), MID(`patients`.`work_phone`,4,3), RIGHT(`patients`.`work_phone`,4)) as 'work_phone', CONCAT_WS('-', LEFT(`patients`.`mobile`,3), MID(`patients`.`mobile`,4,3)) as 'mobile', `patients`.`tobacco_usage` as 'tobacco_usage', `patients`.`alcohol_intake` as 'alcohol_intake', `patients`.`history` as 'history', `patients`.`surgical_history` as 'surgical_history', `patients`.`obstetric_history` as 'obstetric_history', `patients`.`genetic_diseases` as 'genetic_diseases', `patients`.`contact_person` as 'contact_person', `patients`.`other_details` as 'other_details', `patients`.`comments` as 'comments', DATE_FORMAT(`patients`.`filed`, '%c/%e/%Y %l:%i%p') as 'filed', DATE_FORMAT(`patients`.`last_modified`, '%c/%e/%Y %l:%i%p') as 'last_modified'",
141             
'disease_symptoms' => "`disease_symptoms`.`id` as 'id', `disease_symptoms`.`disease` as 'disease', `disease_symptoms`.`symptoms` as 'symptoms', `disease_symptoms`.`reference` as 'reference'",
142             
'medical_records' => "`medical_records`.`id` as 'id', IF( CHAR_LENGTH(`patients1`.`last_name`) || CHAR_LENGTH(`patients1`.`first_name`), CONCAT_WS('', `patients1`.`last_name`, ',', `patients1`.`first_name`), '') as 'patient', `medical_records`.`image_1` as 'image_1', `medical_records`.`image_2` as 'image_2', `medical_records`.`image_3` as 'image_3', `medical_records`.`image_4` as 'image_4', `medical_records`.`image_5` as 'image_5', `medical_records`.`document_1` as 'document_1', `medical_records`.`document_2` as 'document_2', `medical_records`.`document_3` as 'document_3', `medical_records`.`document_4` as 'document_4', `medical_records`.`document_5` as 'document_5', `medical_records`.`description` as 'description'",
143             
'events' => "`events`.`id` as 'id', `events`.`title` as 'title', if(`events`.`date`,date_format(`events`.`date`,'%m/%d/%Y'),'') as 'date', `events`.`status` as 'status', IF( CHAR_LENGTH(`patients1`.`last_name`) || CHAR_LENGTH(`patients1`.`first_name`), CONCAT_WS('', `patients1`.`last_name`, ',', `patients1`.`first_name`), '') as 'name_patient', TIME_FORMAT(`events`.`time`, '%r') as 'time', `events`.`prescription` as 'prescription', `events`.`diagnosis` as 'diagnosis', `events`.`comments` as 'comments'"
144         );
145
146         
if(isset($sql_fields[$table_name])){
147             
return $sql_fields[$table_name];
148         }
149
150         
return false;
151     }
152
153     #########################################################
154
155     function get_sql_from($table_name, $skip_permissions =
false){
156         $sql_from = array(
157             
'patients' => "`patients` ",
158             
'disease_symptoms' => "`disease_symptoms` ",
159             
'medical_records' => "`medical_records` LEFT JOIN `patients` as patients1 ON `patients1`.`id`=`medical_records`.`patient` ",
160             
'events' => "`events` LEFT JOIN `patients` as patients1 ON `patients1`.`id`=`events`.`name_patient` "
161         );
162
163         $pkey = array(
164             
'patients' => 'id',
165             
'disease_symptoms' => 'id',
166             
'medical_records' => 'id',
167             
'events' => 'id'
168         );
169
170         
if(isset($sql_from[$table_name])){
171             
if($skip_permissions) return $sql_from[$table_name];
172
173             
// mm: build the query based on current member's permissions
174             $perm = getTablePermissions($table_name);
175             
if($perm[2] == 1){ // view owner only
176                 $sql_from[$table_name] .=
", membership_userrecords WHERE `{$table_name}`.`{$pkey[$table_name]}`=membership_userrecords.pkValue and membership_userrecords.tableName='{$table_name}' and lcase(membership_userrecords.memberID)='" . getLoggedMemberID() . "'";
177             }elseif($perm[
2] == 2){ // view group only
178                 $sql_from[$table_name] .=
", membership_userrecords WHERE `{$table_name}`.`{$pkey[$table_name]}`=membership_userrecords.pkValue and membership_userrecords.tableName='{$table_name}' and membership_userrecords.groupID='" . getLoggedGroupID() . "'";
179             }elseif($perm[
2] == 3){ // view all
180                 $sql_from[$table_name] .=
' WHERE 1=1';
181             }
else{ // view none
182                 
return false;
183             }
184             
return $sql_from[$table_name];
185         }
186
187         
return false;
188     }
189
190     #########################################################
191
192     function get_joined_record($table, $id, $skip_permissions =
false){
193         $sql_fields = get_sql_fields($table);
194         $sql_from = get_sql_from($table, $skip_permissions);
195
196         
if(!$sql_fields || !$sql_from) return false;
197
198         $pk = getPKFieldName($table);
199         
if(!$pk) return false;
200
201         $safe_id = makeSafe($id,
false);
202         $sql =
"SELECT {$sql_fields} FROM {$sql_from} AND `{$table}`.`{$pk}`='{$safe_id}'";
203         $eo[
'silentErrors'] = true;
204         $res = sql($sql, $eo);
205         
if($row = db_fetch_assoc($res)) return $row;
206
207         
return false;
208     }
209
210     #########################################################
211
212     function get_defaults($table){
213         
/* array of tables and their fields, with default values (or empty), excluding automatic values */
214         $defaults = array(
215             
'patients' => array(
216                 
'id' => '',
217                 
'last_name' => '',
218                 
'first_name' => '',
219                 
'gender' => 'Unknown',
220                 
'sexual_orientation' => 'Unknown',
221                 
'birth_date' => '',
222                 
'age' => '',
223                 
'image' => '',
224                 
'address' => '',
225                 
'city' => '',
226                 
'state' => '',
227                 
'zip' => '',
228                 
'home_phone' => '',
229                 
'work_phone' => '',
230                 
'mobile' => '',
231                 
'tobacco_usage' => 'Unknown',
232                 
'alcohol_intake' => 'Unknown',
233                 
'history' => 'Unknown',
234                 
'surgical_history' => '',
235                 
'obstetric_history' => '',
236                 
'genetic_diseases' => '',
237                 
'contact_person' => '',
238                 
'other_details' => '',
239                 
'comments' => '',
240                 
'filed' => '',
241                 
'last_modified' => ''
242             ),
243             
'disease_symptoms' => array(
244                 
'id' => '',
245                 
'disease' => '',
246                 
'symptoms' => '',
247                 
'reference' => ''
248             ),
249             
'medical_records' => array(
250                 
'id' => '',
251                 
'patient' => '',
252                 
'image_1' => '',
253                 
'image_2' => '',
254                 
'image_3' => '',
255                 
'image_4' => '',
256                 
'image_5' => '',
257                 
'document_1' => '',
258                 
'document_2' => '',
259                 
'document_3' => '',
260                 
'document_4' => '',
261                 
'document_5' => '',
262                 
'description' => ''
263             ),
264             
'events' => array(
265                 
'id' => '',
266                 
'title' => '',
267                 
'date' => '',
268                 
'status' => '',
269                 
'name_patient' => '',
270                 
'time' => '12:00',
271                 
'prescription' => '',
272                 
'diagnosis' => '',
273                 
'comments' => ''
274             )
275         );
276
277         
return isset($defaults[$table]) ? $defaults[$table] : array();
278     }
279
280     #########################################################
281
282     function getLoggedGroupID(){
283         
if($_SESSION['memberGroupID']!=''){
284             
return $_SESSION['memberGroupID'];
285         }
else{
286             
if(!setAnonymousAccess()) return false;
287             
return getLoggedGroupID();
288         }
289     }
290
291     #########################################################
292
293     function getLoggedMemberID(){
294         
if($_SESSION['memberID']!=''){
295             
return strtolower($_SESSION['memberID']);
296         }
else{
297             
if(!setAnonymousAccess()) return false;
298             
return getLoggedMemberID();
299         }
300     }
301
302     #########################################################
303
304     function setAnonymousAccess(){
305         $adminConfig = config(
'adminConfig');
306         $anon_group_safe = addslashes($adminConfig[
'anonymousGroup']);
307         $anon_user_safe = strtolower(addslashes($adminConfig[
'anonymousMember']));
308
309         $eo = array(
'silentErrors' => true);
310
311         $res = sql(
"select groupID from membership_groups where name='{$anon_group_safe}'", $eo);
312         
if(!$res){ return false; }
313         $row = db_fetch_array($res); $anonGroupID = $row[
0];
314
315         $_SESSION[
'memberGroupID'] = ($anonGroupID ? $anonGroupID : 0);
316
317         $res = sql(
"select lcase(memberID) from membership_users where lcase(memberID)='{$anon_user_safe}' and groupID='{$anonGroupID}'", $eo);
318         
if(!$res){ return false; }
319         $row = db_fetch_array($res); $anonMemberID = $row[
0];
320
321         $_SESSION[
'memberID'] = ($anonMemberID ? $anonMemberID : 0);
322
323         
return true;
324     }
325
326     #########################################################
327
328     function logInMember(){
329         $redir =
'index.php';
330         
if($_POST['signIn'] != ''){
331             
if($_POST['username'] != '' && $_POST['password'] != ''){
332                 $username = makeSafe(strtolower($_POST[
'username']));
333                 $password = md5($_POST[
'password']);
334
335                 
if(sqlValue("select count(1) from membership_users where lcase(memberID)='$username' and passMD5='$password' and isApproved=1 and isBanned=0")==1){
336                     $_SESSION[
'memberID']=$username;
337                     $_SESSION[
'memberGroupID']=sqlValue("select groupID from membership_users where lcase(memberID)='$username'");
338                     
if($_POST['rememberMe']==1){
339                         @setcookie(
'online_clinic_management_system_rememberMe', md5($username.$password), time()+86400*30);
340                     }
else{
341                         @setcookie(
'online_clinic_management_system_rememberMe', '', time()-86400*30);
342                     }
343
344                     
// hook: login_ok
345                     
if(function_exists('login_ok')){
346                         $args=array();
347                         
if(!$redir=login_ok(getMemberInfo(), $args)){
348                             $redir=
'index.php';
349                         }
350                     }
351
352                     redirect($redir);
353                     exit;
354                 }
355             }
356
357             
// hook: login_failed
358             
if(function_exists('login_failed')){
359                 $args=array();
360                 login_failed(array(
361                     
'username' => $_POST['username'],
362                     
'password' => $_POST['password'],
363                     
'IP' => $_SERVER['REMOTE_ADDR']
364                     ), $args);
365             }
366
367             
if(!headers_sent()) header('HTTP/1.0 403 Forbidden');
368             redirect(
"index.php?loginFailed=1");
369             exit;
370         }elseif((!$_SESSION[
'memberID'] || $_SESSION['memberID']==$adminConfig['anonymousMember']) && $_COOKIE['online_clinic_management_system_rememberMe']!=''){
371             $chk=makeSafe($_COOKIE[
'online_clinic_management_system_rememberMe']);
372             
if($username=sqlValue("select memberID from membership_users where convert(md5(concat(memberID, passMD5)), char)='$chk' and isBanned=0")){
373                 $_SESSION[
'memberID']=$username;
374                 $_SESSION[
'memberGroupID']=sqlValue("select groupID from membership_users where lcase(memberID)='$username'");
375             }
376         }
377     }
378
379     #########################################################
380
381     function logOutMember(){
382         logOutUser();
383         redirect(
"index.php?signIn=1");
384     }
385
386     #########################################################
387
388     function htmlUserBar(){
389         
global $adminConfig, $Translation;
390         
if(!defined('PREPEND_PATH')) define('PREPEND_PATH', '');
391
392         ob_start();
393         $home_page = (basename($_SERVER[
'PHP_SELF'])=='index.php' ? true : false);
394
395         ?>
396         <nav
class="navbar navbar-default navbar-fixed-top hidden-print" role="navigation">
397             <div
class="navbar-header">
398                 <button type=
"button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
399                     <span
class="sr-only">Toggle navigation</span>
400                     <span
class="icon-bar"></span>
401                     <span
class="icon-bar"></span>
402                     <span
class="icon-bar"></span>
403                 </button>
404                 <!-- application title
is obtained from the name besides the yellow database icon in AppGini, use underscores for spaces -->
405                 <a
class="navbar-brand" href="<?php echo PREPEND_PATH; ?>index.php"><i class="glyphicon glyphicon-home"></i> online clinic management system</a>
406             </div>
407             <div
class="collapse navbar-collapse">
408                 <ul
class="nav navbar-nav">
409                     <?php
if(!$home_page){ ?>
410                         <?php echo NavMenus(); ?>
411                     <?php } ?>
412                 </ul>
413
414                 <?php
if(getLoggedAdmin()){ ?>
415                     <ul
class="nav navbar-nav">
416                         <a href=
"<?php echo PREPEND_PATH; ?>admin/pageHome.php" class="btn btn-danger navbar-btn hidden-xs" title="<?php echo html_attr($Translation['admin area']); ?>"><i class="glyphicon glyphicon-cog"></i> <?php echo $Translation['admin area']; ?></a>
417                         <a href=
"<?php echo PREPEND_PATH; ?>admin/pageHome.php" class="btn btn-danger navbar-btn visible-xs btn-lg" title="<?php echo html_attr($Translation['admin area']); ?>"><i class="glyphicon glyphicon-cog"></i> <?php echo $Translation['admin area']; ?></a>
418                     </ul>
419                 <?php } ?>
420
421                 <?php
if(!$_GET['signIn'] && !$_GET['loginFailed']){ ?>
422                     <?php
if(getLoggedMemberID() == $adminConfig['anonymousMember']){ ?>
423                         <p
class="navbar-text navbar-right">&nbsp;</p>
424                         <a href=
"<?php echo PREPEND_PATH; ?>index.php?signIn=1" class="btn btn-success navbar-btn navbar-right"><?php echo $Translation['sign in']; ?></a>
425                         <p
class="navbar-text navbar-right">
426                             <?php echo $Translation[
'not signed in']; ?>
427                         </p>
428                     <?php }
else{ ?>
429                         <ul
class="nav navbar-nav navbar-right hidden-xs" style="min-width: 330px;">
430                             <a
class="btn navbar-btn btn-default" href="<?php echo PREPEND_PATH; ?>index.php?signOut=1"><i class="glyphicon glyphicon-log-out"></i> <?php echo $Translation['sign out']; ?></a>
431                             <p
class="navbar-text">
432                                 <?php echo $Translation[
'signed as']; ?> <strong><a href="<?php echo PREPEND_PATH; ?>membership_profile.php" class="navbar-link"><?php echo getLoggedMemberID(); ?></a></strong>
433                             </p>
434                         </ul>
435                         <ul
class="nav navbar-nav visible-xs">
436                             <a
class="btn navbar-btn btn-default btn-lg visible-xs" href="<?php echo PREPEND_PATH; ?>index.php?signOut=1"><i class="glyphicon glyphicon-log-out"></i> <?php echo $Translation['sign out']; ?></a>
437                             <p
class="navbar-text text-center">
438                                 <?php echo $Translation[
'signed as']; ?> <strong><a href="<?php echo PREPEND_PATH; ?>membership_profile.php" class="navbar-link"><?php echo getLoggedMemberID(); ?></a></strong>
439                             </p>
440                         </ul>
441                         <script>
442                             
/* periodically check if user is still signed in */
443                             setInterval(function(){
444                                 $j.ajax({
445                                     url:
'<?php echo PREPEND_PATH; ?>ajax_check_login.php',
446                                     success: function(username){
447                                         
if(!username.length) window.location = '<?php echo PREPEND_PATH; ?>index.php?signIn=1';
448                                     }
449                                 });
450                             },
60000);
451                         </script>
452                     <?php } ?>
453                 <?php } ?>
454             </div>
455         </nav>
456         <?php
457
458         $html = ob_get_contents();
459         ob_end_clean();
460
461         
return $html;
462     }
463
464     #########################################################
465
466     function showNotifications($msg =
'', $class = '', $fadeout = true){
467         
global $Translation;
468
469         $notify_template_no_fadeout =
'<div id="%%ID%%" class="alert alert-dismissable %%CLASS%%" style="display: none; padding-top: 6px; padding-bottom: 6px;">' .
470                     
'<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' .
471                     
'%%MSG%%</div>' .
472                     
'<script> jQuery(function(){ jQuery("#%%ID%%").show("slow"); }); </script>'."\n";
473         $notify_template =
'<div id="%%ID%%" class="alert %%CLASS%%" style="display: none; padding-top: 6px; padding-bottom: 6px;">%%MSG%%</div>' .
474                     
'<script>' .
475                         
'jQuery(function(){' .
476                             
'jQuery("#%%ID%%").show("slow", function(){' .
477                                 
'setTimeout(function(){ jQuery("#%%ID%%").hide("slow"); }, 4000);' .
478                             
'});' .
479                         
'});' .
480                     
'</script>'."\n";
481
482         
if(!$msg){ // if no msg, use url to detect message to display
483             
if($_REQUEST['record-added-ok'] != ''){
484                 $msg = $Translation[
'new record saved'];
485                 $
class = 'alert-success';
486             }elseif($_REQUEST[
'record-added-error'] != ''){
487                 $msg = $Translation[
'Couldn\'t save the new record'];
488                 $
class = 'alert-danger';
489                 $fadeout =
false;
490             }elseif($_REQUEST[
'record-updated-ok'] != ''){
491                 $msg = $Translation[
'record updated'];
492                 $
class = 'alert-success';
493             }elseif($_REQUEST[
'record-updated-error'] != ''){
494                 $msg = $Translation[
'Couldn\'t save changes to the record'];
495                 $
class = 'alert-danger';
496                 $fadeout =
false;
497             }elseif($_REQUEST[
'record-deleted-ok'] != ''){
498                 $msg = $Translation[
'The record has been deleted successfully'];
499                 $
class = 'alert-success';
500                 $fadeout =
false;
501             }elseif($_REQUEST[
'record-deleted-error'] != ''){
502                 $msg = $Translation[
'Couldn\'t delete this record'];
503                 $
class = 'alert-danger';
504                 $fadeout =
false;
505             }
else{
506                 
return '';
507             }
508         }
509         $id =
'notification-' . rand();
510
511         $
out = ($fadeout ? $notify_template : $notify_template_no_fadeout);
512         $
out = str_replace('%%ID%%', $id, $out);
513         $
out = str_replace('%%MSG%%', $msg, $out);
514         $
out = str_replace('%%CLASS%%', $class, $out);
515
516         
return $out;
517     }
518
519     #########################################################
520
521     function parseMySQLDate($date, $altDate){
522         
// is $date valid?
523         
if(preg_match("/^\d{4}-\d{1,2}-\d{1,2}$/", trim($date))){
524             
return trim($date);
525         }
526
527         
if($date != '--' && preg_match("/^\d{4}-\d{1,2}-\d{1,2}$/", trim($altDate))){
528             
return trim($altDate);
529         }
530
531         
if($date != '--' && $altDate && intval($altDate)==$altDate){
532             
return @date('Y-m-d', @time() + ($altDate >= 1 ? $altDate - 1 : $altDate) * 86400);
533         }
534
535         
return '';
536     }
537
538     #########################################################
539
540     function parseCode($code, $isInsert=
true, $rawData=false){
541         
if($isInsert){
542             $arrCodes=array(
543                 
'<%%creatorusername%%>' => $_SESSION['memberID'],
544                 
'<%%creatorgroupid%%>' => $_SESSION['memberGroupID'],
545                 
'<%%creatorip%%>' => $_SERVER['REMOTE_ADDR'],
546                 
'<%%creatorgroup%%>' => sqlValue("select name from membership_groups where groupID='{$_SESSION['memberGroupID']}'"),
547
548                 
'<%%creationdate%%>' => ($rawData ? @date('Y-m-d') : @date('n/j/Y')),
549                 
'<%%creationtime%%>' => ($rawData ? @date('H:i:s') : @date('h:i:s a')),
550                 
'<%%creationdatetime%%>' => ($rawData ? @date('Y-m-d H:i:s') : @date('n/j/Y h:i:s a')),
551                 
'<%%creationtimestamp%%>' => ($rawData ? @date('Y-m-d H:i:s') : @time())
552             );
553         }
else{
554             $arrCodes=array(
555                 
'<%%editorusername%%>' => $_SESSION['memberID'],
556                 
'<%%editorgroupid%%>' => $_SESSION['memberGroupID'],
557                 
'<%%editorip%%>' => $_SERVER['REMOTE_ADDR'],
558                 
'<%%editorgroup%%>' => sqlValue("select name from membership_groups where groupID='{$_SESSION['memberGroupID']}'"),
559
560                 
'<%%editingdate%%>' => ($rawData ? @date('Y-m-d') : @date('n/j/Y')),
561                 
'<%%editingtime%%>' => ($rawData ? @date('H:i:s') : @date('h:i:s a')),
562                 
'<%%editingdatetime%%>' => ($rawData ? @date('Y-m-d H:i:s') : @date('n/j/Y h:i:s a')),
563                 
'<%%editingtimestamp%%>' => ($rawData ? @date('Y-m-d H:i:s') : @time())
564             );
565         }
566
567         $pc=str_ireplace(array_keys($arrCodes), array_values($arrCodes), $code);
568
569         
return $pc;
570     }
571
572     #########################################################
573
574     function addFilter($index, $filterAnd, $filterField, $filterOperator, $filterValue){
575         
// validate input
576         
if($index < 1 || $index > 80 || !is_int($index)) return false;
577         
if($filterAnd != 'or') $filterAnd = 'and';
578         $filterField = intval($filterField);
579
580         
/* backward compatibility */
581         
if(in_array($filterOperator, $GLOBALS['filter_operators'])){
582             $filterOperator = array_search($filterOperator, $GLOBALS[
'filter_operators']);
583         }
584
585         
if(!in_array($filterOperator, array_keys($GLOBALS['filter_operators']))){
586             $filterOperator =
'like';
587         }
588
589         
if(!$filterField){
590             $filterOperator =
'';
591             $filterValue =
'';
592         }
593
594         $_REQUEST[
'FilterAnd'][$index] = $filterAnd;
595         $_REQUEST[
'FilterField'][$index] = $filterField;
596         $_REQUEST[
'FilterOperator'][$index] = $filterOperator;
597         $_REQUEST[
'FilterValue'][$index] = $filterValue;
598
599         
return true;
600     }
601
602     #########################################################
603
604     function clearFilters(){
605         
for($i=1; $i<=80; $i++){
606             addFilter($i,
'', 0, '', '');
607         }
608     }
609
610     #########################################################
611
612     function getMemberInfo($memberID =
''){
613         
static $member_info = array();
614
615         
if(!$memberID){
616             $memberID = getLoggedMemberID();
617         }
618
619         
// return cached results, if present
620         
if(isset($member_info[$memberID])) return $member_info[$memberID];
621
622         $adminConfig = config(
'adminConfig');
623         $mi = array();
624
625         
if($memberID){
626             $res = sql(
"select * from membership_users where memberID='" . makeSafe($memberID) . "'", $eo);
627             
if($row = db_fetch_assoc($res)){
628                 $mi = array(
629                     
'username' => $memberID,
630                     
'groupID' => $row['groupID'],
631                     
'group' => sqlValue("select name from membership_groups where groupID='{$row['groupID']}'"),
632                     
'admin' => ($adminConfig['adminUsername'] == $memberID ? true : false),
633                     
'email' => $row['email'],
634                     
'custom' => array(
635                         $row[
'custom1'],
636                         $row[
'custom2'],
637                         $row[
'custom3'],
638                         $row[
'custom4']
639                     ),
640                     
'banned' => ($row['isBanned'] ? true : false),
641                     
'approved' => ($row['isApproved'] ? true : false),
642                     
'signupDate' => @date('n/j/Y', @strtotime($row['signupDate'])),
643                     
'comments' => $row['comments'],
644                     
'IP' => $_SERVER['REMOTE_ADDR']
645                 );
646
647                 
// cache results
648                 $member_info[$memberID] = $mi;
649             }
650         }
651
652         
return $mi;
653     }
654
655     #########################################################
656
657     
if(!function_exists('str_ireplace')){
658         function str_ireplace($search, $replace, $subject){
659             $ret=$subject;
660             
if(is_array($search)){
661                 
for($i=0; $i<count($search); $i++){
662                     $ret=str_ireplace($search[$i], $replace[$i], $ret);
663                 }
664             }
else{
665                 $ret=preg_replace(
'/'.preg_quote($search, '/').'/i', $replace, $ret);
666             }
667
668             
return $ret;
669         }
670     }
671
672     #########################################################
673
674     
/**
675     * Loads a given view
from the templates folder, passing the given data to it
676     * @param $view the name of a php file (without extension) to be loaded
from the 'templates' folder
677     * @param $the_data_to_pass_to_the_view (optional) associative array containing the data to pass to the view
678     * @
return the output of the parsed view as a string
679     */

680     function loadView($view, $the_data_to_pass_to_the_view=
false){
681         
global $Translation;
682
683         $view = dirname(__FILE__).
"/templates/$view.php";
684         
if(!is_file($view)) return false;
685
686         
if(is_array($the_data_to_pass_to_the_view)){
687             
foreach($the_data_to_pass_to_the_view as $k => $v)
688                 $$k = $v;
689         }
690         unset($the_data_to_pass_to_the_view, $k, $v);
691
692         ob_start();
693         @include($view);
694         $
out=ob_get_contents();
695         ob_end_clean();
696
697         
return $out;
698     }
699
700     #########################################################
701
702     
/**
703     * Loads a table template
from the templates folder, passing the given data to it
704     * @param $table_name the name of the table whose template
is to be loaded from the 'templates' folder
705     * @param $the_data_to_pass_to_the_table associative array containing the data to pass to the table template
706     * @
return the output of the parsed table template as a string
707     */

708     function loadTable($table_name, $the_data_to_pass_to_the_table = array()){
709         $dont_load_header = $the_data_to_pass_to_the_table[
'dont_load_header'];
710         $dont_load_footer = $the_data_to_pass_to_the_table[
'dont_load_footer'];
711
712         $header = $table = $footer =
'';
713
714         
if(!$dont_load_header){
715             
// try to load tablename-header
716             
if(!($header = loadView("{$table_name}-header", $the_data_to_pass_to_the_table))){
717                 $header = loadView(
'table-common-header', $the_data_to_pass_to_the_table);
718             }
719         }
720
721         $table = loadView($table_name, $the_data_to_pass_to_the_table);
722
723         
if(!$dont_load_footer){
724             
// try to load tablename-footer
725             
if(!($footer = loadView("{$table_name}-footer", $the_data_to_pass_to_the_table))){
726                 $footer = loadView(
'table-common-footer', $the_data_to_pass_to_the_table);
727             }
728         }
729
730         
return "{$header}{$table}{$footer}";
731     }
732
733     #########################################################
734
735     function filterDropdownBy($filterable, $filterers, $parentFilterers, $parentPKField, $parentCaption, $parentTable, &$filterableCombo){
736         $filterersArray = explode(
',', $filterers);
737         $parentFilterersArray = explode(
',', $parentFilterers);
738         $parentFiltererList =
'`' . implode('`, `', $parentFilterersArray) . '`';
739         $res=sql(
"SELECT `$parentPKField`, $parentCaption, $parentFiltererList FROM `$parentTable` ORDER BY 2", $eo);
740         $filterableData = array();
741         
while($row=db_fetch_row($res)){
742             $filterableData[$row[
0]] = $row[1];
743             $filtererIndex =
0;
744             
foreach($filterersArray as $filterer){
745                 $filterableDataByFilterer[$filterer][$row[$filtererIndex +
2]][$row[0]] = $row[1];
746                 $filtererIndex++;
747             }
748             $row[
0] = addslashes($row[0]);
749             $row[
1] = addslashes($row[1]);
750             $jsonFilterableData .=
"\"{$row[0]}\":\"{$row[1]}\",";
751         }
752         $jsonFilterableData .=
'}';
753         $jsonFilterableData =
'{'.str_replace(',}', '}', $jsonFilterableData);
754         $filterJS =
"\nvar {$filterable}_data = $jsonFilterableData;";
755
756         
foreach($filterersArray as $filterer){
757             
if(is_array($filterableDataByFilterer[$filterer])) foreach($filterableDataByFilterer[$filterer] as $filtererItem => $filterableItem){
758                 $jsonFilterableDataByFilterer[$filterer] .=
'"'.addslashes($filtererItem).'":{';
759                 
foreach($filterableItem as $filterableItemID => $filterableItemData){
760                     $jsonFilterableDataByFilterer[$filterer] .=
'"'.addslashes($filterableItemID).'":"'.addslashes($filterableItemData).'",';
761                 }
762                 $jsonFilterableDataByFilterer[$filterer] .=
'},';
763             }
764             $jsonFilterableDataByFilterer[$filterer] .=
'}';
765             $jsonFilterableDataByFilterer[$filterer] =
'{'.str_replace(',}', '}', $jsonFilterableDataByFilterer[$filterer]);
766
767             $filterJS.=
"\n\n// code for filtering {$filterable} by {$filterer}\n";
768             $filterJS.=
"\nvar {$filterable}_data_by_{$filterer} = {$jsonFilterableDataByFilterer[$filterer]}; ";
769             $filterJS.=
"\nvar selected_{$filterable} = \$j('#{$filterable}').val();";
770             $filterJS.=
"\nvar {$filterable}_change_by_{$filterer} = function(){";
771             $filterJS.=
"\n\t$('{$filterable}').options.length=0;";
772             $filterJS.=
"\n\t$('{$filterable}').options[0] = new Option();";
773             $filterJS.=
"\n\tif(\$j('#{$filterer}').val()){";
774             $filterJS.=
"\n\t\tfor({$filterable}_item in {$filterable}_data_by_{$filterer}[\$j('#{$filterer}').val()]){";
775             $filterJS.=
"\n\t\t\t$('{$filterable}').options[$('{$filterable}').options.length] = new Option(";
776             $filterJS.=
"\n\t\t\t\t{$filterable}_data_by_{$filterer}[\$j('#{$filterer}').val()][{$filterable}_item],";
777             $filterJS.=
"\n\t\t\t\t{$filterable}_item,";
778             $filterJS.=
"\n\t\t\t\t({$filterable}_item == selected_{$filterable} ? true : false),";
779             $filterJS.=
"\n\t\t\t\t({$filterable}_item == selected_{$filterable} ? true : false)";
780             $filterJS.=
"\n\t\t\t);";
781             $filterJS.=
"\n\t\t}";
782             $filterJS.=
"\n\t}else{";
783             $filterJS.=
"\n\t\tfor({$filterable}_item in {$filterable}_data){";
784             $filterJS.=
"\n\t\t\t$('{$filterable}').options[$('{$filterable}').options.length] = new Option(";
785             $filterJS.=
"\n\t\t\t\t{$filterable}_data[{$filterable}_item],";
786             $filterJS.=
"\n\t\t\t\t{$filterable}_item,";
787             $filterJS.=
"\n\t\t\t\t({$filterable}_item == selected_{$filterable} ? true : false),";
788             $filterJS.=
"\n\t\t\t\t({$filterable}_item == selected_{$filterable} ? true : false)";
789             $filterJS.=
"\n\t\t\t);";
790             $filterJS.=
"\n\t\t}";
791             $filterJS.=
"\n\t\tif(selected_{$filterable} && selected_{$filterable} == \$j('#{$filterable}').val()){";
792             $filterJS.=
"\n\t\t\tfor({$filterer}_item in {$filterable}_data_by_{$filterer}){";
793             $filterJS.=
"\n\t\t\t\tfor({$filterable}_item in {$filterable}_data_by_{$filterer}[{$filterer}_item]){";
794             $filterJS.=
"\n\t\t\t\t\tif({$filterable}_item == selected_{$filterable}){";
795             $filterJS.=
"\n\t\t\t\t\t\t$('{$filterer}').value = {$filterer}_item;";
796             $filterJS.=
"\n\t\t\t\t\t\tbreak;";
797             $filterJS.=
"\n\t\t\t\t\t}";
798             $filterJS.=
"\n\t\t\t\t}";
799             $filterJS.=
"\n\t\t\t\tif({$filterable}_item == selected_{$filterable}) break;";
800             $filterJS.=
"\n\t\t\t}";
801             $filterJS.=
"\n\t\t}";
802             $filterJS.=
"\n\t}";
803             $filterJS.=
"\n\t$('{$filterable}').highlight();";
804             $filterJS.=
"\n};";
805             $filterJS.=
"\n$('{$filterer}').observe('change', function(){ window.setTimeout({$filterable}_change_by_{$filterer}, 25); });";
806             $filterJS.=
"\n";
807         }
808
809         $filterableCombo =
new Combo;
810         $filterableCombo->ListType =
0;
811         $filterableCombo->ListItem = array_slice(array_values($filterableData),
0, 10);
812         $filterableCombo->ListData = array_slice(array_keys($filterableData),
0, 10);
813         $filterableCombo->SelectName = $filterable;
814         $filterableCombo->AllowNull =
true;
815
816         
return $filterJS;
817     }
818
819     #########################################################
820     function br2nl($text){
821         
return preg_replace('/\<br(\s*)?\/?\>/i', "\n", $text);
822     }
823
824     #########################################################
825
826     
if(!function_exists('htmlspecialchars_decode')){
827         function htmlspecialchars_decode($
string, $quote_style = ENT_COMPAT){
828             
return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
829         }
830     }
831
832     #########################################################
833
834     function entitiesToUTF8($input){
835         
return preg_replace_callback('/(&#[0-9]+;)/', '_toUTF8', $input);
836     }
837
838     function _toUTF8($m){
839         
if(function_exists('mb_convert_encoding')){
840             
return mb_convert_encoding($m[1], "UTF-8", "HTML-ENTITIES");
841         }
else{
842             
return $m[1];
843         }
844     }
845
846     #########################################################
847
848     function func_get_args_byref() {
849         
if(!function_exists('debug_backtrace')) return false;
850
851         $trace = debug_backtrace();
852         
return $trace[1]['args'];
853     }
854
855     #########################################################
856
857     function permissions_sql($table, $level =
'all'){
858         
if(!in_array($level, array('user', 'group'))){ $level = 'all'; }
859         $perm = getTablePermissions($table);
860         $
from = '';
861         $
where = '';
862         $pk = getPKFieldName($table);
863
864         
if($perm[2] == 1 || ($perm[2] > 1 && $level == 'user')){ // view owner only
865             $
from = 'membership_userrecords';
866             $
where = "(`$table`.`$pk`=membership_userrecords.pkValue and membership_userrecords.tableName='$table' and lcase(membership_userrecords.memberID)='".getLoggedMemberID()."')";
867         }elseif($perm[
2] == 2 || ($perm[2] > 2 && $level == 'group')){ // view group only
868             $
from = 'membership_userrecords';
869             $
where = "(`$table`.`$pk`=membership_userrecords.pkValue and membership_userrecords.tableName='$table' and membership_userrecords.groupID='".getLoggedGroupID()."')";
870         }elseif($perm[
2] == 3){ // view all
871             
// no further action
872         }elseif($perm[
2] == 0){ // view none
873             
return false;
874         }
875
876         
return array('where' => $where, 'from' => $from, 0 => $where, 1 => $from);
877     }
878
879     #########################################################
880
881     function error_message($msg, $back_url =
'', $full_page = true){
882         $curr_dir = dirname(__FILE__);
883         
global $Translation;
884
885         ob_start();
886
887         
if($full_page) include_once($curr_dir . '/header.php');
888
889         echo
'<div class="panel panel-danger">';
890             echo
'<div class="panel-heading"><h3 class="panel-title">' . $Translation['error:'] . '</h3></div>';
891             echo
'<div class="panel-body"><p class="text-danger">' . $msg . '</p>';
892             
if($back_url !== false){ // explicitly passing false suppresses the back link completely
893                 echo
'<div class="text-center">';
894                 
if($back_url){
895                     echo
'<a href="' . $back_url . '" class="btn btn-danger btn-lg vspacer-lg"><i class="glyphicon glyphicon-chevron-left"></i> ' . $Translation['< back'] . '</a>';
896                 }
else{
897                     echo
'<a href="#" class="btn btn-danger btn-lg vspacer-lg" onclick="history.go(-1); return false;"><i class="glyphicon glyphicon-chevron-left"></i> ' . $Translation['< back'] . '</a>';
898                 }
899                 echo
'</div>';
900             }
901             echo
'</div>';
902         echo
'</div>';
903
904         
if($full_page) include_once($curr_dir . '/footer.php');
905
906         $
out = ob_get_contents();
907         ob_end_clean();
908
909         
return $out;
910     }
911
912     #########################################################
913
914     function toMySQLDate($formattedDate, $sep = datalist_date_separator, $ord = datalist_date_format){
915         
// extract date elements
916         $de=explode($sep, $formattedDate);
917         $mySQLDate=intval($de[strpos($ord,
'Y')]).'-'.intval($de[strpos($ord, 'm')]).'-'.intval($de[strpos($ord, 'd')]);
918         
return $mySQLDate;
919     }
920
921     #########################################################
922
923     function reIndex(&$arr){
924         $i=
1;
925         
foreach($arr as $n=>$v){
926             $arr2[$i]=$n;
927             $i++;
928         }
929         
return $arr2;
930     }
931
932     #########################################################
933
934     function get_embed($provider, $url, $max_width =
'', $max_height = '', $retrieve = 'html'){
935         
global $Translation;
936         
if(!$url) return '';
937
938         $providers = array(
939             
'youtube' => array('oembed' => 'http://www.youtube.com/oembed?'),
940             
'googlemap' => array('oembed' => '', 'regex' => '/^http.*\.google\..*maps/i')
941         );
942
943         
if(!isset($providers[$provider])){
944             
return '<div class="text-danger">' . $Translation['invalid provider'] . '</div>';
945         }
946
947         
if(isset($providers[$provider]['regex']) && !preg_match($providers[$provider]['regex'], $url)){
948             
return '<div class="text-danger">' . $Translation['invalid url'] . '</div>';
949         }
950
951         
if($providers[$provider]['oembed']){
952             $oembed = $providers[$provider][
'oembed'] . 'url=' . urlencode($url) . "&maxwidth={$max_width}&maxheight={$max_height}&format=json";
953             $data_json = request_cache($oembed);
954
955             $data = json_decode($data_json,
true);
956             
if($data === null){
957                 
/* an error was returned rather than a json string */
958                 
if($retrieve == 'html') return "<div class=\"text-danger\">{$data_json}\n<!-- {$oembed} --></div>";
959                 
return '';
960             }
961
962             
return (isset($data[$retrieve]) ? $data[$retrieve] : $data['html']);
963         }
964
965         
/* special cases (where there is no oEmbed provider) */
966         
if($provider == 'googlemap') return get_embed_googlemap($url, $max_width, $max_height, $retrieve);
967
968         
return '<div class="text-danger">Invalid provider!</div>';
969     }
970
971     #########################################################
972
973     function get_embed_googlemap($url, $max_width =
'', $max_height = '', $retrieve = 'html'){
974         
global $Translation;
975         $url_parts = parse_url($url);
976         $coords_regex =
'/-?\d+(\.\d+)?[,+]-?\d+(\.\d+)?(,\d{1,2}z)?/'; /* https://stackoverflow.com/questions/2660201 */
977
978         
if(preg_match($coords_regex, $url_parts['path'] . '?' . $url_parts['query'], $m)){
979             list($lat, $
long, $zoom) = explode(',', $m[0]);
980             $zoom = intval($zoom);
981             
if(!$zoom) $zoom = 10; /* default zoom */
982             
if(!$max_height) $max_height = 360;
983             
if(!$max_width) $max_width = 480;
984
985             $api_key =
'';
986             $embed_url =
"https://www.google.com/maps/embed/v1/view?key={$api_key}&center={$lat},{$long}&zoom={$zoom}&maptype=roadmap";
987             $thumbnail_url =
"https://maps.googleapis.com/maps/api/staticmap?key={$api_key}&center={$lat},{$long}&zoom={$zoom}&maptype=roadmap&size={$max_width}x{$max_height}";
988
989             
if($retrieve == 'html'){
990                 
return "<iframe width=\"{$max_width}\" height=\"{$max_height}\" frameborder=\"0\" style=\"border:0\" src=\"{$embed_url}\"></iframe>";
991             }
else{
992                 
return $thumbnail_url;
993             }
994         }
else{
995             
return '<div class="text-danger">' . $Translation['cant retrieve coordinates from url'] . '</div>';
996         }
997     }
998
999     #########################################################
1000
1001     function request_cache($request, $force_fetch =
false){
1002         $max_cache_lifetime =
7 * 86400; /* max cache lifetime in seconds before refreshing from source */
1003
1004         
/* membership_cache table exists? if not, create it */
1005         
static $cache_table_exists = false;
1006         
if(!$cache_table_exists && !$force_fetch){
1007             $te = sqlValue(
"show tables like 'membership_cache'");
1008             
if(!$te){
1009                 
if(!sql("CREATE TABLE `membership_cache` (`request` VARCHAR(100) NOT NULL, `request_ts` INT, `response` TEXT NOT NULL, PRIMARY KEY (`request`))", $eo)){
1010                     
/* table can't be created, so force fetching request */
1011                     
return request_cache($request, true);
1012                 }
1013             }
1014             $cache_table_exists =
true;
1015         }
1016
1017         
/* retrieve response from cache if exists */
1018         
if(!$force_fetch){
1019             $res = sql(
"select response, request_ts from membership_cache where request='" . md5($request) . "'", $eo);
1020             
if(!$row = db_fetch_array($res)) return request_cache($request, true);
1021
1022             $response = $row[
0];
1023             $response_ts = $row[
1];
1024             
if($response_ts < time() - $max_cache_lifetime) return request_cache($request, true);
1025         }
1026
1027         
/* if no response in cache, issue a request */
1028         
if(!$response || $force_fetch){
1029             $response = @file_get_contents($request);
1030             
if($response === false){
1031                 $error = error_get_last();
1032                 $error_message = preg_replace(
'/.*: (.*)/', '$1', $error['message']);
1033                 
return $error_message;
1034             }elseif($cache_table_exists){
1035                 
/* store response in cache */
1036                 $ts = time();
1037                 sql(
"replace into membership_cache set request='" . md5($request) . "', request_ts='{$ts}', response='" . makeSafe($response, false) . "'", $eo);
1038             }
1039         }
1040
1041         
return $response;
1042     }
1043
1044     #########################################################
1045
1046     function check_record_permission($table, $id, $perm =
'view'){
1047         
if($perm != 'edit' && $perm != 'delete') $perm = 'view';
1048
1049         $perms = getTablePermissions($table);
1050         
if(!$perms[$perm]) return false;
1051
1052         $safe_id = makeSafe($id);
1053         $safe_table = makeSafe($table);
1054
1055         
if($perms[$perm] == 1){ // own records only
1056             $username = getLoggedMemberID();
1057             $owner = sqlValue(
"select memberID from membership_userrecords where tableName='{$safe_table}' and pkValue='{$safe_id}'");
1058             
if($owner == $username) return true;
1059         }elseif($perms[$perm] ==
2){ // group records
1060             $group_id = getLoggedGroupID();
1061             $owner_group_id = sqlValue(
"select groupID from membership_userrecords where tableName='{$safe_table}' and pkValue='{$safe_id}'");
1062             
if($owner_group_id == $group_id) return true;
1063         }elseif($perms[$perm] ==
3){ // all records
1064             
return true;
1065         }
1066
1067         
return false;
1068     }
1069
1070     #########################################################
1071
1072     function NavMenus($options = array()){
1073         
if(!defined('PREPEND_PATH')) define('PREPEND_PATH', '');
1074         
global $Translation;
1075         $prepend_path = PREPEND_PATH;
1076
1077         
/* default options */
1078         
if(empty($options)){
1079             $options = array(
1080                 
'tabs' => 7
1081             );
1082         }
1083
1084         $table_group_name = array_keys(get_table_groups());
/* 0 => group1, 1 => group2 .. */
1085         
/* if only one group named 'None', set to translation of 'select a table' */
1086         
if((count($table_group_name) == 1 && $table_group_name[0] == 'None') || count($table_group_name) < 1) $table_group_name[0] = $Translation['select a table'];
1087         $table_group_index = array_flip($table_group_name);
/* group1 => 0, group2 => 1 .. */
1088         $menu = array_fill(
0, count($table_group_name), '');
1089
1090         $t = time();
1091         $arrTables = getTableList();
1092         
if(is_array($arrTables)){
1093             
foreach($arrTables as $tn => $tc){
1094                 
/* ---- list of tables where hide link in nav menu is set ---- */
1095                 $tChkHL = array_search($tn, array(
'medical_records'));
1096
1097                 
/* ---- list of tables where filter first is set ---- */
1098                 $tChkFF = array_search($tn, array());
1099                 
if($tChkFF !== false && $tChkFF !== null){
1100                     $searchFirst =
'&Filter_x=1';
1101                 }
else{
1102                     $searchFirst =
'';
1103                 }
1104
1105                 
/* when no groups defined, $table_group_index['None'] is NULL, so $menu_index is still set to 0 */
1106                 $menu_index = intval($table_group_index[$tc[
3]]);
1107                 
if(!$tChkHL && $tChkHL !== 0) $menu[$menu_index] .= "<li><a href=\"{$prepend_path}{$tn}_view.php?t={$t}{$searchFirst}\"><img src=\"{$prepend_path}" . ($tc[2] ? $tc[2] : 'blank.gif') . "\" height=\"32\"> {$tc[0]}</a></li>";
1108             }
1109         }
1110
1111         
// custom nav links, as defined in "hooks/links-navmenu.php"
1112         
global $navLinks;
1113         
if(is_array($navLinks)){
1114             $memberInfo = getMemberInfo();
1115             $links_added = array();
1116             
foreach($navLinks as $link){
1117                 
if(!isset($link['url']) || !isset($link['title'])) continue;
1118                 
if($memberInfo['admin'] || @in_array($memberInfo['group'], $link['groups']) || @in_array('*', $link['groups'])){
1119                     $menu_index = intval($link[
'table_group']);
1120                     
if(!$links_added[$menu_index]) $menu[$menu_index] .= '<li class="divider"></li>';
1121
1122                     
/* add prepend_path to custom links if they aren't absolute links */
1123                     
if(!preg_match('/^(http|\/\/)/i', $link['url'])) $link['url'] = $prepend_path . $link['url'];
1124                     
if(!preg_match('/^(http|\/\/)/i', $link['icon']) && $link['icon']) $link['icon'] = $prepend_path . $link['icon'];
1125
1126                     $menu[$menu_index] .=
"<li><a href=\"{$link['url']}\"><img src=\"" . ($link['icon'] ? $link['icon'] : "{$prepend_path}blank.gif") . "\" height=\"32\"> {$link['title']}</a></li>";
1127                     $links_added[$menu_index]++;
1128                 }
1129             }
1130         }
1131
1132         $menu_wrapper =
'';
1133         
for($i = 0; $i < count($menu); $i++){
1134             $menu_wrapper .= <<<EOT
1135                 <li
class="dropdown">
1136                     <a href=
"#" class="dropdown-toggle" data-toggle="dropdown">{$table_group_name[$i]} <b class="caret"></b></a>
1137                     <ul
class="dropdown-menu" role="menu">{$menu[$i]}</ul>
1138                 </li>
1139 EOT;
1140         }
1141
1142         
return $menu_wrapper;
1143     }
1144
1145     #########################################################
1146
1147     function StyleSheet(){
1148         
if(!defined('PREPEND_PATH')) define('PREPEND_PATH', '');
1149         $prepend_path = PREPEND_PATH;
1150
1151         $css_links = <<<EOT
1152
1153             <link rel=
"stylesheet" href="{$prepend_path}resources/initializr/css/bootstrap.css">
1154             <!--[
if gt IE 8]><!-->
1155                 <link rel=
"stylesheet" href="{$prepend_path}resources/initializr/css/bootstrap-theme.css">
1156             <!--<![endif]-->
';
1157             <link rel=
"stylesheet" href="{$prepend_path}resources/lightbox/css/lightbox.css" media="screen">
1158             <link rel=
"stylesheet" href="{$prepend_path}resources/select2/select2.css" media="screen">
1159             <link rel=
"stylesheet" href="{$prepend_path}resources/timepicker/bootstrap-timepicker.min.css" media="screen">
1160             <link rel=
"stylesheet" href="{$prepend_path}dynamic.css.php">
1161 EOT;
1162
1163         
return $css_links;
1164     }
1165
1166     #########################################################
1167
1168     function getUploadDir($dir){
1169         
global $Translation;
1170
1171         
if($dir==""){
1172             $dir=$Translation[
'ImageFolder'];
1173         }
1174
1175         
if(substr($dir, -1)!="/"){
1176             $dir.=
"/";
1177         }
1178
1179         
return $dir;
1180     }
1181
1182     #########################################################
1183
1184     function PrepareUploadedFile($FieldName, $MaxSize, $FileTypes=
'jpg|jpeg|gif|png', $NoRename=false, $dir=""){
1185         
global $Translation;
1186         $f = $_FILES[$FieldName];
1187
1188         $dir = getUploadDir($dir);
1189
1190         
/* get php.ini upload_max_filesize in bytes */
1191         $php_upload_size_limit = trim(ini_get(
'upload_max_filesize'));
1192         $last = strtolower($php_upload_size_limit[strlen($php_upload_size_limit)-
1]);
1193         
switch($last){
1194             
case 'g':
1195                 $php_upload_size_limit *=
1024;
1196             
case 'm':
1197                 $php_upload_size_limit *=
1024;
1198             
case 'k':
1199                 $php_upload_size_limit *=
1024;
1200         }
1201
1202         $MaxSize = min($MaxSize, $php_upload_size_limit);
1203
1204         
if($f['error'] != 4 && $f['name']!=''){
1205             
if($f['size']>$MaxSize || $f['error']){
1206                 echo error_message(str_replace(
'<MaxSize>', intval($MaxSize / 1024), $Translation['file too large']));
1207                 exit;
1208             }
1209             
if(!preg_match('/\.('.$FileTypes.')$/i', $f['name'], $ft)){
1210                 echo error_message(str_replace(
'<FileTypes>', str_replace('|', ', ', $FileTypes), $Translation['invalid file type']));
1211                 exit;
1212             }
1213
1214             
if($NoRename){
1215                 $n = str_replace(
' ', '_', $f['name']);
1216             }
else{
1217                 $n = microtime();
1218                 $n = str_replace(
' ', '_', $n);
1219                 $n = str_replace(
'0.', '', $n);
1220                 $n .= $ft[
0];
1221             }
1222
1223             
if(!file_exists($dir)){
1224                 @mkdir($dir,
0777);
1225             }
1226
1227             
if(!@move_uploaded_file($f['tmp_name'], $dir . $n)){
1228                 echo error_message(
"Couldn't save the uploaded file. Try chmoding the upload folder '{$dir}' to 777.");
1229                 exit;
1230             }
else{
1231                 @chmod($dir.$n,
0666);
1232                 
return $n;
1233             }
1234         }
1235         
return "";
1236     }
1237
1238     #########################################################
1239
1240     function get_home_links($homeLinks, $default_classes, $tgroup =
''){
1241         
if(!is_array($homeLinks) || !count($homeLinks)) return '';
1242
1243         $memberInfo = getMemberInfo();
1244
1245         ob_start();
1246         
foreach($homeLinks as $link){
1247             
if(!isset($link['url']) || !isset($link['title'])) continue;
1248             
if($tgroup != $link['table_group'] && $tgroup != '*') continue;
1249
1250             
/* fall-back classes if none defined */
1251             
if(!$link['grid_column_classes']) $link['grid_column_classes'] = $default_classes['grid_column'];
1252             
if(!$link['panel_classes']) $link['panel_classes'] = $default_classes['panel'];
1253             
if(!$link['link_classes']) $link['link_classes'] = $default_classes['link'];
1254
1255             
if($memberInfo['admin'] || @in_array($memberInfo['group'], $link['groups']) || @in_array('*', $link['groups'])){
1256                 ?>
1257                 <div
class="col-xs-12 <?php echo $link['grid_column_classes']; ?>">
1258                     <div
class="panel <?php echo $link['panel_classes']; ?>">
1259                         <div
class="panel-body">
1260                             <a
class="btn btn-block btn-lg <?php echo $link['link_classes']; ?>" title="<?php echo preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", html_attr(strip_tags($link['description']))); ?>" href="<?php echo $link['url']; ?>"><?php echo ($link['icon'] ? '<img src="' . $link['icon'] . '">' : ''); ?><strong><?php echo $link['title']; ?></strong></a>
1261                             <div
class="panel-body-description"><?php echo $link['description']; ?></div>
1262                         </div>
1263                     </div>
1264                 </div>
1265                 <?php
1266             }
1267         }
1268
1269         $html = ob_get_contents();
1270         ob_end_clean();
1271
1272         
return $html;
1273     }
1274
1275     #########################################################


Gõ tìm kiếm nhanh...